package org.example.java.util.concurrency.thread.condition;

import java.util.PriorityQueue;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by juntaozhang on 3/12/15.
 */
public class ConsumerProducerTest {
  private int queueSize = 10;
  private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);
  private Lock lock = new ReentrantLock();
  private Condition notFull = lock.newCondition();
  private Condition notEmpty = lock.newCondition();
  Random random = new Random(37);

  public static void main(String[] args) {
    ConsumerProducerTest test = new ConsumerProducerTest();
    Producer producer = test.new Producer("producer");
    Consumer consumer = test.new Consumer("consumer");

    producer.start();
    consumer.start();
  }

  class Consumer extends Thread {

    public Consumer(String name) {
      super(name);
    }

    @Override
    public void run() {
      consume();
    }

    private void consume() {
      while (true) {
        System.out.println(getName() + "-begin");
        lock.lock();
        System.out.println(getName() + "-lock");
        try {
          TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        try {
          while (queue.size() == 0) {
            try {
              System.out.println(getName() + "-队列空，等待数据");
              notEmpty.await();
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }
          System.out.println(getName() + "-取出数据：" + queue.poll()); //每次移走队首元素
          notFull.signal();
          System.out.println(getName() + "-从队列取走一个元素，队列剩余" + queue.size() + "个元素");
        } finally {
          System.out.println(getName() + "-unlock");
          lock.unlock();
        }
        System.out.println(getName() + "-end");
      }
    }
  }

  class Producer extends Thread {
    public Producer(String name) {
      super(name);
    }

    @Override
    public void run() {
      produce();
    }

    private void produce() {
      while (true) {
        System.out.println(getName() + "-begin");
        lock.lock();
        System.out.println(getName() + "-lock");
        try {
          TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        try {
          while (queue.size() == queueSize) {
            try {
              System.out.println(getName() + "-队列满，等待有空余空间");
              notFull.await();
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }
          int aInt = random.nextInt(100);
          System.out.println(getName() + "-插入数据：" + aInt);
          queue.offer(aInt); //每次插入一个元素
          notEmpty.signal();
          System.out.println(getName() + "-向队列取中插入一个元素，队列剩余空间：" + (queueSize - queue.size()));
        } finally {
          System.out.println(getName() + "-unlock");
          lock.unlock();
        }
        System.out.println(getName() + "-end");
      }
    }
  }
}